package com.cwnu.sw.cys.core.common.config;

import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.springframework.core.env.Environment;
/**
 * @author jisam
 * @version 1.0
 * @contact "jisamchan@outlook.com"
 * @date 22/03/2025
 * @description Swagger 配置类
 */
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig {
    /**
     * 创建Swagger Docket配置实例
     * @return Docket对象，包含Swagger接口文档的完整配置
     */
    @Bean(value = "defaultApi2")
    Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                // 配置接口文档的基本信息
                .apiInfo(new ApiInfoBuilder()
                        .title("mallchat接口文档")
                        .version("v1.0")
                        .description("mallchat接口文档")
                        .contact(new Contact("诒森", "/", "jisamchan@outlook.com"))
                        .build())
                .select()
                // 指定需要扫描的接口范围
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 配置Actuator端点的Web处理映射
     * @param webEndpointsSupplier 提供Web端点信息的供应商
     * @param servletEndpointsSupplier 提供Servlet端点信息的供应商
     * @param controllerEndpointsSupplier 提供Controller端点信息的供应商
     * @param endpointMediaTypes 端点支持的媒体类型配置
     * @param corsProperties 跨域资源共享配置属性
     * @param webEndpointProperties Web端点全局配置属性
     * @param environment 系统环境变量
     * @return WebMvcEndpointHandlerMapping实例，用于处理端点请求映射
     */
    @Bean
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(
            WebEndpointsSupplier webEndpointsSupplier,
            ServletEndpointsSupplier servletEndpointsSupplier,
            ControllerEndpointsSupplier controllerEndpointsSupplier,
            EndpointMediaTypes endpointMediaTypes,
            CorsEndpointProperties corsProperties,
            WebEndpointProperties webEndpointProperties,
            Environment environment) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        // 收集所有类型的端点信息
        allEndpoints.addAll(webEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());

        // 配置基础路径和端点映射
        String basePath = webEndpointProperties.getBasePath();
        EndpointMapping endpointMapping = new EndpointMapping(basePath);

        // 判断是否需要注册链接映射
        boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(
                webEndpointProperties, environment, basePath);

        return new WebMvcEndpointHandlerMapping(
                endpointMapping,
                webEndpointsSupplier.getEndpoints(),
                endpointMediaTypes,
                corsProperties.toCorsConfiguration(),
                new EndpointLinksResolver(allEndpoints, basePath),
                shouldRegisterLinksMapping,
                null);
    }

    /**
     * 判断是否需要注册端点链接映射
     * @param webEndpointProperties Web端点配置属性
     * @param environment 系统环境变量
     * @param basePath 端点基础路径
     * @return 是否需要注册链接映射的布尔值
     */
    private boolean shouldRegisterLinksMapping(
            WebEndpointProperties webEndpointProperties,
            Environment environment,
            String basePath) {
        return webEndpointProperties.getDiscovery().isEnabled()
                && (StringUtils.hasText(basePath)
                || Objects.equals(ManagementPortType.get(environment),
                ManagementPortType.DIFFERENT));
    }
}
